﻿using System.ComponentModel;
using System.Runtime.Serialization;

namespace SharpGL.SceneGraph.Assets
{
    /// <summary>
    /// An Asset is something which is used in the scene, but is not in the scene 
    /// tree. An example of an asset is a material, which there may be one instance
    /// of which is shared between many objects.
    /// </summary>
    [DataContract(/*IsReference = true, */Name = "Asset", Namespace = "SharpGL.SceneGraph")]
    public abstract class Asset : INotifyPropertyChanged
    {
        #region Private Consts

        private static readonly int defaultID = 0;
        private static readonly string defaultName = "Asset";
        
        #endregion Private Consts

        #region Private Fields

        [DataMember()]
        private int id;

        [DataMember()]
        private string name;

        #endregion Private Fields

        #region Private Methods

        [OnDeserialized]
        private void OnDeserialized(StreamingContext ctx)
        {
            OnDeserialized();
        }

        [OnDeserializing]
        private void OnDeserializing(StreamingContext ctx)
        {
            OnDeserializing();
        }

        #endregion Private Methods

        #region Protected Methods

        /// <summary>
        /// Call this function to do the PropertyChanged event.
        /// </summary>
        protected void NotifyPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        protected virtual void OnDeserialized()
        {
        }

        protected virtual void OnDeserializing()
        {
        }

        #endregion Protected Methods

        #region Public Constructors

        public Asset()
        {
            id = defaultID;
            name = (defaultName == null ? "" : (string)defaultName.Clone());
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// a <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return GetType().Name + ": " + Name;
        }

        #endregion

        #region Public Events

        [Description("Called when properties has been changed."), Category("SharpGL")]
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion Public Events

        #region Properies

        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>
        /// The id.
        /// </value>
        [Description("The unique ID of the Asset."), Category("Asset")]
        public int Id
        {
            get { return this.id; }
            set
            {
                if (this.id != value)
                {
                    this.id = value;

                    NotifyPropertyChanged("ID");
                }
            }
        }

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        /// <value>
        /// The name.
        /// </value>
        [Description("The name of the Asset."), Category("Assrt")]
        public string Name
        {
            get { return this.name; }
            set
            {
                if (this.name != value)
                {
                    this.name = value;

                    NotifyPropertyChanged("Name");
                }
            }
        }

        #endregion
    }
}
